#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <vector>
#include <QThread>
#include "../glutil/ModelRenderer.h"
#include "../glutil/shaderUtils.h"
#include "../glutil/FreeCamera.h"
#include "../glutil/Impostor.h"
#include "../glutil/TerrainRenderer.h"
#include "slotsData/ForestState.h"
#include "slotsData/SpeciesProperties.h"
#include "slotsData/ImageProperties.h"
#include "slotsData/GroundProperties.h"
#include "slotsData/SkyProperties.h"

#include "../sceneelems/sky.h"
#include "../sceneelems/grass.h"
#include "postprocess.h"
#include <QGLWidget>
#include <QBasicTimer>

class MainWidget : public QGLWidget
{
    Q_OBJECT

    public:
        MainWidget(QWidget *parent = 0);
        ~MainWidget();

    public slots:
		void forestChanged(slotsdata::ForestState state);
		void speciesChanged(slotsdata::SpeciesProperties properties);
		void imagePropertiesChanged(slotsdata::ImageProperties properties);
		void groundDataChanged(slotsdata::GroundProperties properties);
		void skyDataChanged(slotsdata::SkyProperties properties);

	signals:
		void selectedTree(int treeID);
		void initializeSky();
    protected:
		void timerEvent(QTimerEvent *event);
        void setCamera();
        void set2DCamera();
        void initializeGL();
        void paintGL();
        void setGLLight();
		void update3DModel();
		void reconstructForestFromData();

        void resizeGL(int width, int height);
        void mousePressEvent(QMouseEvent *event);
        void mouseMoveEvent(QMouseEvent *event);
        void wheelEvent(QWheelEvent * event);
        void keyPressEvent ( QKeyEvent * event );
		void keyReleaseEvent ( QKeyEvent * event );

		void renderPickingBuffer();
		void pickTree(int x, int y);
	private:

		class RendererInfo
		{
			public:
				QString speciesFile;
				int fileModel;
				float baseScale;
				bool operator<(RendererInfo other) const
				{
					if(speciesFile<other.speciesFile)
						return true;
					if(speciesFile>other.speciesFile)
						return false;

					return fileModel<other.fileModel;
				}
		};

        int widgetWidth;
        int widgetHeight;
		int m_selectedTree;
		glutil::FreeCamera * m_camera;
        QPoint lastPos;
		slotsdata::ForestState currentForest;
		slotsdata::SpeciesProperties currentSpecies;
        std::map<RendererInfo, glutil::ModelRenderer> m_treeRenderers;
        std::map<RendererInfo, glutil::Impostor> m_treeImpostors;
		std::vector<geom::BSphere> m_treeBoundingSpheres;
		glutil::ModelRenderer * m_dummyTreeRenderer;
		glutil::Impostor * m_dummyImpostor;
		float * m_pickingBuffer;
		bool m_pickingBufferUpToDate;
		auto_ptr<geom::PolyObject> m_dummyObject;
        geom::TerrainModel m_currentTerrain;
		auto_ptr<glutil::TerrainRenderer> m_terrainRenderer;
		bool m_mustMoveDirections[4];
		enum MoveDirections{M_FRONT,M_RIGHT,M_BACK,M_LEFT};
		QBasicTimer timer;
		sceneelems::Sky m_sky;
        auto_ptr<sceneelems::Grass> m_grass;

		PostProcess * m_postProcess;
};

#endif

